// config/config.go
package config

import (
	"bsm/models"
	"os"
	"strconv"
	"sync"
	"time"
)

type Config struct {
	AppConfig    *models.AppConfig
	DesignConfig *models.ProjectDesignConfig
	RedisConfig  *models.RedisConfig
}

var (
	instance *Config
	once     sync.Once
)

func Init() *Config {
	once.Do(func() {
		instance = &Config{
			AppConfig:    loadAppConfig(),
			DesignConfig: loadProjectConfig(),
			RedisConfig:  loadRedisConfig(),
		}
	})
	return instance
}

func Get() *Config {
	if instance == nil {
		panic("config not initialized, call config.Init() first")
	}
	return instance
}

// 具体的加载函数
func loadAppConfig() *models.AppConfig {
	return &models.AppConfig{
		SessionMaxPerUser: getEnvAsInt("SESSION_MAX_PER_USER", 3),
		JWTSecret:         getEnv("JWT_SECRET", "default-secret"),
		ServerPort:        getEnv("SERVER_PORT", "8080"),
	}
}

func loadProjectConfig() *models.ProjectDesignConfig {
	return &models.ProjectDesignConfig{
		VatRate:  getEnvAsFloat("RATE_TAX", 0.9),
		SafeRate: getEnvAsFloat("RATE_SAFE", 0.02),
		DiscountRates: models.DiscountRates{
			DiscountLabor:      getEnvAsFloat("DISCOUNT_LABOR", 0.25),
			DiscountMachine:    getEnvAsFloat("DISCOUNT_MACHINE", 0),
			DiscountInstrument: getEnvAsFloat("DISCOUNT_INSTRUMENT", 0),
			DiscountMeasure:    getEnvAsFloat("DISCOUNT_MEASURE", 0.25),
			DiscountManagement: getEnvAsFloat("DISCOUNT_MANAGEMENT", 0.25),
			DiscountProfit:     getEnvAsFloat("DISCOUNT_PROFIT", 0.25),
		},
	}
}

func loadRedisConfig() *models.RedisConfig {
	return &models.RedisConfig{
		Addr:         getEnv("REDIS_ADDR", "localhost:6379"),
		Password:     getEnv("REDIS_PASSWORD", ""),
		DB:           getEnvAsInt("REDIS_DB", 0),
		PoolSize:     getEnvAsInt("REDIS_POOL_SIZE", 100),
		MinIdleConns: getEnvAsInt("REDIS_MIN_IDLE", 10),
		DialTimeout:  time.Second * 5,
		ReadTimeout:  time.Second * 3,
		WriteTimeout: time.Second * 3,
	}
}

// 辅助函数保持不变...
func getEnv(key, defaultValue string) string {
	if value, exists := os.LookupEnv(key); exists {
		return value
	}
	return defaultValue
}

func getEnvAsInt(key string, defaultValue int) int {
	if value, exists := os.LookupEnv(key); exists {
		if intVal, err := strconv.Atoi(value); err == nil {
			return intVal
		}
	}
	return defaultValue
}

func getEnvAsFloat(key string, defaultValue float64) float64 {
	if value, exists := os.LookupEnv(key); exists {
		if floatVal, err := strconv.ParseFloat(value, 64); err == nil {
			return floatVal
		}
	}
	return defaultValue
}
